package com.smcaiot.filesync.starter.handler.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.smcaiot.filesync.starter.annotation.Base64Field;
import com.smcaiot.filesync.starter.annotation.SmallPath;
import com.smcaiot.filesync.starter.app.HandlerContext;
import com.smcaiot.filesync.starter.constants.HandlerType;
import com.smcaiot.filesync.starter.entity.Base64Param;
import com.smcaiot.filesync.starter.entity.FindNotPullListParams;
import com.smcaiot.filesync.starter.entity.FinishPullParams;
import com.smcaiot.filesync.starter.handler.SyncFileHandler;
import com.smcaiot.filesync.starter.util.ReflectTool;
import com.smcaiot.filesync.starter.util.RestResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static com.smcaiot.filesync.starter.constants.Constants.URL_FIND_NOT_PULL_LIST;
import static com.smcaiot.filesync.starter.constants.Constants.URL_FINISH_PULL;

/**
 * @Author: cz
 * @Date: 2023/7/3
 * @Description:
 */
@Slf4j
public class AbstractPullFileHandler<T> extends BaseHandler<T> implements SyncFileHandler<T> {

    @Autowired
    private HandlerContext handlerContext;

    @Override
    public List<T> findNotSyncList() {
        FindNotPullListParams params = new FindNotPullListParams();
        Class genericClass = ReflectTool.getGenericParameterClass(this.getClass());
        params.setHandlerType(HandlerType.pull).setEntityClassName(genericClass.getSimpleName());
        return findNotPullList(params);
    }

    private List<T> findNotPullList(FindNotPullListParams params) {
        try (HttpResponse response = HttpUtil.createPost(getFindNotPullListUrl()).headerMap(getHeaderMap(), true)
                .body(JSONUtil.toJsonStr(params)).execute()) {
            String resultStr = response.body();
            RestResp restResp = JSONUtil.toBean(resultStr, RestResp.class);
            if (!RestResp.CODE_SUCCESS.equals(restResp.getCode()) || Objects.isNull(restResp.getData())) {
                log.warn("查询未拉取文件列表接口失败：{}", JSONUtil.toJsonStr(restResp));
                return new ArrayList<>();
            }
            Class genericClass = ReflectTool.getGenericParameterClass(this.getClass());
            return JSONUtil.toList(JSONUtil.parseArray(restResp.getData()), genericClass);
        }
    }

    private String getFindNotPullListUrl() {
        return Objects.isNull(remoteInfo) || StrUtil.isBlank(remoteInfo.getUrl()) ?
                fileSyncProp.getPull().getRemoteHost() + URL_FIND_NOT_PULL_LIST : remoteInfo.getUrl();
    }

    @Override
    public boolean syncFile(T entity) {
        String filePath = ReflectTool.getFieldValue(entity, SmallPath.class);
        if (StrUtil.isBlank(filePath)) {
            log.debug("拉取文件时，找不到文件地址");
            return false;
        }
        String base64 = ReflectTool.getFieldValue(entity, Base64Field.class);
        Base64Param base64Param = new Base64Param().setOriginName(true).setBase64(base64)
                .setFilePath(fileSyncProp.getBaseDir() + "/" + getNameByPath(filePath));
        String uploadPath = fileHandler.uploadBase64(base64Param);
        if (StrUtil.isBlank(uploadPath)) {
            return false;
        }
        BeanUtil.setProperty(entity, ReflectTool.getFieldName(entity, Base64Field.class), null);
        Class<T> genericClz = ReflectTool.getGenericParameterClass(this.getClass());
        T newEntity = JSONUtil.toBean(JSONUtil.toJsonStr(entity), genericClz);
        return finish(Collections.singletonList(newEntity));
    }

    public boolean finishPull(List<T> list) {
        Class genericClass = ReflectTool.getGenericParameterClass(this.getClass());
        FinishPullParams params = new FinishPullParams().setList(list);
        params.setHandlerType(HandlerType.pull).setEntityClassName(genericClass.getSimpleName());
        try (HttpResponse response = HttpUtil.createPost(getFinishPullUrl()).headerMap(getHeaderMap(), true)
                .body(JSONUtil.toJsonStr(params)).execute()) {
            String resultStr = response.body();
            RestResp restResp = JSONUtil.toBean(resultStr, RestResp.class);
            if (!RestResp.CODE_SUCCESS.equals(restResp.getCode()) || Objects.isNull(restResp.getData())) {
                log.warn("完成拉取回调接口失败：{}", JSONUtil.toJsonStr(restResp));
                return false;
            }
            return (boolean) restResp.getData();
        }
    }

    private String getFinishPullUrl() {
        return Objects.isNull(remoteInfo) || StrUtil.isBlank(remoteInfo.getUrl()) ?
                fileSyncProp.getPull().getRemoteHost() + URL_FINISH_PULL : remoteInfo.getUrl();
    }

}
